package simulation;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;
import javax.swing.JButton;
import javax.swing.JPanel;

/**
 * Canvas class that encompasses the game in the window. 
 * Starts the game thread. Handles game end, restart, pause, and splash screen.
 *
 */
/**
 * @author Volodymyr, Rex
 *
 */
public class Canvas extends JPanel implements Runnable {
    /** If no key is pressed, the value is -1.*/
    public static final int NO_KEY_PRESSED = -1;

    private ResourceBundle myResources;
    private int myWidth;
    private int myHeight;
    private boolean myGameIsRunning;
    private boolean myShowSplash;
    private boolean myRestart;

    private GameWindow myFrame;
    private JButton myButton;
    private Thread myNewRound;
    private Game myGame;

    /**
     * Constructor for the canvas.
     * @param resource the resource bundle to use
     * @param width of the canvas
     * @param height of the canvas
     * @param gameWindow that created the canvas
     */
    public Canvas(ResourceBundle resource, int width,
            int height, GameWindow gameWindow) {
        setPreferredSize(new Dimension(width, height));
        setFocusable(true);
        //setLayout(new BorderLayout());
        myWidth = width;
        myHeight = height;
        myResources = resource;
        myFrame = gameWindow;
        myGameIsRunning = false;
        myShowSplash = true;
        //if the game has started for more than one time
        myRestart = false;
        addButton(myResources.getString("StartButton"), width / 2, height / 2);
        //setInputListeners();
        myGame = null;
    }

    private void addButton(String message, int x, int y) {
        final int buttonXPos = myWidth * 3 / 4;
        final int buttonYPos = myHeight * 5 / 6;
        final int buttonHeight = 30;
        final int buttonWidth = 100;

        myButton = new JButton(message);
        myButton.setVisible(true);
        myButton.addActionListener(new StartGame());
        add(myButton);
        setLayout(null);
        myButton.setBounds(buttonXPos, buttonYPos, buttonWidth, buttonHeight);
        repaint();
        myFrame.refreshScreen();
    }

    /**
     * Start the Threads and factories for game to run.
     */
    private void startRunning() {
        myNewRound = new Thread(this);
        myNewRound.start();
    }

    /**
     * Paints the canvas (splash screen if
     * not started, or game if started).
     * @param g used to paint
     */
    public void paint(Graphics g) {
        super.paint(g);
        if (myShowSplash) {
            paintSplash(g);
        }
        try {
            myGame.paint(g);
        }
        catch (NullPointerException e) {
            // do nothing if game isn't created yet
        }
    }
    
    @Override
    public void run() {
        myGame = new Game(this);
        addKeyListener(myGame.getObserver());
        int myDelayTime = Integer.parseInt(myResources.getString("Delay"));
        while (myGameIsRunning) {
            myGame.update();
            repaint();
            try {
                myNewRound.sleep(myDelayTime);
            }
            catch (InterruptedException e) {
                System.out.println("The game is paused!");
            }
        }
    }

    /**
     * Always paint splash image in the center of the Canvas.
     *
     * @param g Graphics
     */
    private void paintSplash(Graphics g) {
        Image splashImage = GameWindow.importImage(myResources, "SplashImage");
        int myXCoordinate = myWidth / 2 - splashImage.getWidth(null) / 2;
        int myYCoordinate = myHeight / 2 - splashImage.getHeight(null) / 2;
        g.drawImage(splashImage, myXCoordinate, myYCoordinate, this);
        if (myRestart) {
            printStringInCenter(g, myResources.getString("RestartMessage"), 250,
                    Integer.parseInt(myResources.getString("SplashFontSize")));
        }
        else {
            printStringInCenter(g, myResources.getString("StartMessage"), 250,
                    Integer.parseInt(myResources.getString("SplashFontSize")));
        }
    }

    /**
     * Paint the message; aligned in center.
     *
     * @param g Graphcis
     * @param message Message to be displayed
     * @param height vertical position
     * @param fontSize font size
     */
    private void printStringInCenter(Graphics g,
            String message, int height, int fontSize) {
        Font gameFont = new Font("Helvetica", Font.BOLD, fontSize);
        FontMetrics myFontMetrics = this.getFontMetrics(gameFont);
        int r = (int)(Math.random() * 4);
        switch (r) {
            case 0:
                g.setColor(Color.ORANGE); break;
            case 1:
                g.setColor(Color.GREEN); break;
            case 2:
                g.setColor(Color.MAGENTA); break;
            case 3:
                g.setColor(Color.PINK); break;
            default:
                break;
        }
        g.setFont(gameFont);
        g.drawString(message, (myWidth
                - myFontMetrics.stringWidth(message)) / 2, height);
    }

    @Override
    public void paintComponent(Graphics gs) {
        Graphics2D g = (Graphics2D)gs;
        super.paintComponent(g);
        g.drawImage(GameWindow.importImage(myResources, "BackgroundImage"),
                0, 0, myWidth, myHeight, this);
    }

    /**
     * Go to restart screen if game is over.
     */
    public void gameOver() {
        myGameIsRunning = false;
        myShowSplash = true;
        myButton.setVisible(true);
        myButton.setText("Restart");
        myRestart = true;
        repaint();
    }

    /**
     * Gets the resource package to use.
     * @param resource name of package
     * @return the resource package
     */
    public String getResource (String resource) {
        return myResources.getString(resource);
    }

    /**
     * Starts the game after the start
     * button is pressed.
     *
     */
    private class StartGame implements ActionListener {
        public StartGame() {
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //initGameElements();
            myButton.setVisible(false);
            myGameIsRunning = true;
            myShowSplash = false;
            startRunning();
        }
    }
}
